Modular Monoliths and Telegram Mini Apps

In my previous blog post, I described how I was looking into Jeremy Miller's tools for development. Although I think they are terrific tools and still worthy of a look, I made the decision recently to pivot away from them because:

  1. The tools are still in active progress and update frequently,
  2. The documentation lags the active progress and isn't the best place to find answers that you're looking for,
  3. The new stuff is often on Jeremy's blog posts, which makes them difficult to find,
  4. I'd really like to explore what .NET Aspire offers
  5. It's very difficult to use AI Assistant in JetBrains Rider to have it write CritterStack code and uncover problems for me.

I recently subscribed to Steve Smith's (aka "Ardalis") Modular Monoliths class on DomeTrain. So far I like the approach that Steve takes on construction of a monolith with different domain areas. What he didn't cover (nor does he need to as it isn't exactly relevant to his topic) is how to get this working in Aspire. There are some Aspire things that I want to incorporate into Steve's model.

Using Postgres instead of SQL Server

This one was fairly simple. You'll want to use the Aspire.NpgSql.EntityFrameworkCore.PostgreSQL and Npgsql.EntityFrameworkCore.PostgreSQL NuGet packages in your separate monolith domain projects (like Users). In your AppHost project, you'll want the Aspire.Hosting.PostgreSQL NuGet package.

In your AppHost Program.cs file, you'll want to have something like this:

var dbserver = builder.AddPostgres("dbserver")  
    .WithPgAdmin();  

// Keep track of the "yourdb" string - we'll be using it in the Users domain project
var yourDb = dbserver.AddDatabase("yourdb");

Steve recommends creating an Extensions file in your domain projects that add the explicit services you need in that project. You'll be setting up your DbContext here and will need the connection string from the AppHost project. This connection string changes every time you start up your solution, so you'll always need to reference it from AppHost by doing this:

using Microsoft.EntityFrameworkCore;  
using Microsoft.Extensions.Configuration;  
using Microsoft.Extensions.DependencyInjection;  
  
namespace YourAppName.Users;  

// This is the area explicitly setup for Users context
public static class UserServiceExtensions  
{  
    public static IServiceCollection AddUserServices(this IServiceCollection services, IConfiguration configuration)  
    {        services.AddDbContext<UserDbContext>(options =>  
// Make sure that the name you use in the GetConnectionString is the same name you used in AppHost            options.UseNpgsql(configuration.GetConnectionString("yourdb")));  
        services.AddScoped<IUserRepository, EfUserRepository>();  
        services.AddScoped<IUserService, UserService>();  
        return services;  
    }}

Now that we have the connections setup between AppHost and your domain project, we'll tackle setting up migrations.

EF Core Data Migrations in Aspire

In our development environment, we want to conduct EF Core data migrations every time the Aspire AppHost is run. This is due to the fact that Docker containers for your database are constructed and destroyed every time you start and stop the application. You'll most likely want sample data deployed to the database every time you start the application so that you can conduct testing against it. The sample on seeding data on the Microsoft Learn site didn't work me, at least the Seed data using Entity Framework Core section. Setting up a MigrationService project in the solution was an elegant solution to the problem.

Create the project as a Worker project so that it can be added to your AppHost project later on. If you edit your .csproj file, you should see <Project Sdk="Microsoft.NET.Sdk.Worker"> at the top. Your project will depend on two NuGet packages, Microsoft.EntityFrameworkCore and Npgsql.EnityFrameworkCore.PostgreSQL. Also make sure that your project references your domain projects so that you can use their DbContext files in this project.

Your project will have two files in it:

Now every time you deploy and run your app, your database will be setup and ready to go!



Tags: telegram, aspnet

← Back home